using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Reflection;
using System.Collections.ObjectModel;
using System.Diagnostics;
using DDF.Entity;
using System.Runtime.Serialization;

namespace ARR.Entities.ComponentModel
{
    [DataContract]
    [Serializable]
    public abstract class ValidatableEntity : EntityStateTracker, IDataErrorInfo
    {
        [NonSerialized]
        private List<ValidationBase> _inputValidations;
        

        public ValidatableEntity()
        {
            PreventValidationOnNewInstance = false;
        }


        [DataMember]
        public bool PreventValidationOnNewInstance { get; set; }

        public virtual string Error
        {
            get
            {
                string result = this[string.Empty];
                if (result != null && result.Trim().Length == 0)
                {
                    result = null;
                }
                return result;
            }
        }

        public virtual string[] ErrorsList
        {
            get
            {
                if (Error != null)
                {
                    return Error.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
                }

                return null;
            }
        }

        public virtual bool IsValid
        {
            get
            {
                PreventValidationOnNewInstance = false;
                return this.Error == null;
            }
        }
        
        public virtual string this[string propertyName]
        {
            get
            {
                string result = string.Empty;

                if (!PreventValidationOnNewInstance || this.GetEntityState() != EntityState.New)
                {
                    propertyName = CleanString(propertyName);

                    foreach (ValidationBase r in GetBrokenValidations(propertyName))
                    {
                        if (propertyName == string.Empty || r.PropertyName == propertyName)
                        {
                            result += r.ErrorMessage;
                            result += Environment.NewLine;
                        }
                    }
                    result = result.Trim();
                }

                if (result.Length == 0)
                {
                    result = null;
                }

                return result;
            }
        }




        public virtual ReadOnlyCollection<ValidationBase> GetBrokenValidations()
        {
            return GetBrokenValidations(string.Empty);
        }

        public virtual ReadOnlyCollection<ValidationBase> GetBrokenValidations(string property)
        {
            property = CleanString(property);

            if (_inputValidations == null)
            {
                _inputValidations = new List<ValidationBase>();
                _inputValidations.AddRange(this.SetValidations());
            }
            List<ValidationBase> broken = new List<ValidationBase>();


            foreach (ValidationBase r in this._inputValidations)
            {
                if (r.PropertyName == property || property == string.Empty)
                {
                    bool isRuleBroken = !r.Validate(this);
                    Debug.WriteLine(DateTime.Now.ToLongTimeString() + ": Validating the rule: '" + r.ToString() + "' on object '" + this.ToString() + "'. Result = " + ((isRuleBroken == false) ? "Valid" : "Broken"));
                    if (isRuleBroken)
                    {
                        broken.Add(r);
                    }
                }
            }

            return broken.AsReadOnly();
        }

        protected string CleanString(string s)
        {
            return (s ?? string.Empty).Trim();
        }

        protected virtual List<ValidationBase> SetValidations()
        {
            return new List<ValidationBase>();
        }
    }
}